#
# Package.
#

package iSOCK::Model::User;

#
# Dependencies.
#

use Digest::SHA1 qw( sha1_hex );
use Try::Tiny;

#
# Parent.
#

use Moose;
use namespace::autoclean;

BEGIN { extends 'iSOCK::Model::Root' }

#
# Documentation.
#

=head1 NAME

iSOCK::Model::User - Catalyst Model

=head1 DESCRIPTION

Catalyst Model.

=head1 AUTHOR

Xavier Caron

=head1 LICENSE

This library is free software. You can redistribute it and/or modify
it under the same terms as Perl itself.

=cut

#
# Subs.
#

sub delete {
  my ( $self, $option ) = @_;
  
  my ( $c, $id ) = map { $option->{$_} } qw( c id );
  
  if ( my $user_r = $c->model ( 'App::User' )->find ( $id ) ) {
    if ( $user_r->delete ) {
      return 'nuked';
    }
  }
  
  return;
}

sub update {
  my ( $self, $option ) = @_;
  
  my $field = $option->{field};
  
  if ( $option->{product_id} || $option->{specification_id} || $option->{datasheet_id} ) {
    if ( $field =~ /^ authorization_ /x ) {
      return $self->update_authorization    ( $option );
    }
  }
  else {
    if ( $field =~ /^ ( location | mail | name | fake ) $/x ) {
      return $self->update_column           ( $option );
    }
    elsif ( $field =~ /^( can_checkout_specification | can_checkout_datasheet | can_commit_specification | can_commit_datasheet | can_bofh )$/x ) {
      return $self->toggle_role             ( $option );
    }
    elsif ( $field eq 'datasheet_source' ) {
      return $self->update_preference       ( $option );
    }
    elsif ( $field eq 'password' ) {
      return $self->update_password         ( $option );
    }
    elsif ( $field eq 'rest_hash' ) {
      return $self->update_rest_hash        ( $option );
    }
  }
  
  return;
}

sub update_authorization {
  my ( $self, $option ) = @_;
  
  my ( $what, $what_id );
  
  for ( qw( product specification datasheet ) ) {
    next unless $what_id = $option->{"${_}_id"};
    
    $what = $_;
    
    last;
  }
  
  if ( $what ) {
    my $What = ucfirst $what;
    
    my ( $c, $id, $field, $value ) = map { $option->{$_} } qw( c id field value );

    if ( my ( $authorization_id ) = ( $field =~ /^ authorization_ (\w+) $/x ) ) {
      my $model = $c->model ( "App::UserTo$What" );
      my $query = { user_id => $id, "${what}_id" => $what_id, authorization_id => $authorization_id };

      if ( $value eq 'yes' ) {
        if ( $model->update_or_create ( $query ) ) { # FIXME use Try::Tiny
          return $value;
        }
      }
      else {
        if ( my $u2p_r = $model->search ( $query )->single ) {
          if ( $u2p_r->delete ) {
            return $value;
          }
        }
      }
    }
  }
  
  return;
}

sub update_column {
  my ( $self, $option ) = @_;
  
  my ( $c, $id, $field, $value ) = map { $option->{$_} } qw( c id field value );
  
  if ( my $user_r = $c->model ( 'App::User' )->find ( $id ) ) {
    $user_r->set_column ( $field => $value );

    if ( $user_r->update ) {
      return $value;
    }
  }
  
  return;
}

sub toggle_role {
  my ( $self, $option ) = @_;
  
  my ( $c, $id, $field, $value ) = map { $option->{$_} } qw( c id field value );
  
  if ( my $user_r = $c->model ( 'App::User' )->find ( $id ) ) {
    my ( $u2r_r ) = grep { $_->role->id eq $field } $user_r->user_to_roles;
    
    if ( $u2r_r ) {
      if ( $value eq 'no' ) {
        if ( $u2r_r->delete ) {
          return $value;
        }
      }
    }
    else {
      if ( $value eq 'yes' ) {
        if ( my $roles_r = $c->model ( 'App::Role' )->find ( $field ) ) {
          my $u2r_r = $c->model ( 'App::UserToRole' )->create ({ user_id => $id, role_id => $field });
          
          if ( $u2r_r->update ) {
            return $value;
          }
        }
      }
    }
  }
  
  return;
}

sub update_preference {
  my ( $self, $option ) = @_;
  
  my ( $c, $id, $preference, $value ) = map { $option->{$_} } qw( c id field value );
  
  if ( $c->model ( 'App::UserToPreference' )->update_or_create ({ user_id => $id, preference_id => $preference, value => $value }) ) {
    return $value;
  }
  
  return;
}

sub update_password {
  my ( $self, $option ) = @_;
  
  my ( $c, $id, $value ) = map { $option->{$_} } qw( c id value );
  
  if ( my $user_r = $c->model ( 'App::User' )->find ( $id ) ) {
    if ( $value ) {
      my $password = sha1_hex ( $value );

      $user_r->password ( $password );

      if ( $user_r->update ) {
        return substr ( $password, 0, 7 );
      }
    }
    else {
      $user_r->password ( undef );

      if ( $user_r->update ) {
        return '';
      }
    }
  }
  
  return;
}

sub update_rest_hash {
  my ( $self, $option ) = @_;
  
  my ( $c, $id, $value ) = map { $option->{$_} } qw( c id value );
  
  my $hash;
  
  if ( my $user_r = $c->model ( 'App::User' )->find ( $id ) ) {
    $hash = sha1_hex ( $value );
    
    try {
      $user_r->update ({ rest_hash => $hash });
    }
    catch {
      undef $hash;
    };
  }
  
  return $hash;
}

#
# True.
#

1;
